package net.dwade.loader.config;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;

/**
 * 用于对标记 {@link HotSwap} 注解的类进行增强，实现支持动态加载功能
 * @author huangxiaofeng
 * @date 2019/5/19 22:34
 */
public class DynamicAnnotationAdvisor extends AbstractPointcutAdvisor {

    private DynamicReloadContext dynamicReloadContext;

    public DynamicAnnotationAdvisor(DynamicReloadContext dynamicReloadContext) {
        this.dynamicReloadContext = dynamicReloadContext;
    }

    @Override
    public Pointcut getPointcut() {
        return new AnnotationMatchingPointcut(HotSwap.class, true);
    }

    @Override
    public Advice getAdvice() {
        return new DynamicLoaderInterceptor();
    }

    private final class DynamicLoaderInterceptor implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            Class<?> target = AopUtils.getTargetClass(invocation.getThis());
            if (dynamicReloadContext.isReloaded(target)) {
                return dynamicReloadContext.invoke(target, invocation.getMethod(), invocation.getArguments());
            } else {
                return invocation.proceed();
            }
        }
    }

}
